<template>
  <div class="subnet-calculator">
    <el-card>
      <template #header>
        <div class="card-header">
          <h3>子网掩码计算器</h3>
        </div>
      </template>
      
      <el-form :model="form" label-width="120px">
        <el-form-item label="IP地址">
          <el-input v-model="form.ip" placeholder="例如: 192.168.1.1" @input="calculate" />
        </el-form-item>
        
        <el-form-item label="子网掩码">
          <el-select v-model="form.cidr" placeholder="选择CIDR" @change="calculate">
            <el-option
              v-for="i in 32"
              :key="i"
              :label="'/' + i + ' (' + getCidrMask(i) + ')'"
              :value="i"
            />
          </el-select>
        </el-form-item>

        <el-divider>计算结果</el-divider>

        <div class="result" v-if="result.valid">
          <el-descriptions :column="1" border>
            <el-descriptions-item label="网络地址">{{ result.networkAddress }}</el-descriptions-item>
            <el-descriptions-item label="广播地址">{{ result.broadcastAddress }}</el-descriptions-item>
            <el-descriptions-item label="可用IP范围">
              {{ result.firstUsableIp }} - {{ result.lastUsableIp }}
            </el-descriptions-item>
            <el-descriptions-item label="可用IP数量">{{ result.totalHosts }}</el-descriptions-item>
            <el-descriptions-item label="子网掩码">{{ result.subnetMask }}</el-descriptions-item>
          </el-descriptions>
        </div>
        <el-alert
          v-else-if="form.ip"
          type="error"
          :title="result.error"
          show-icon
        />
      </el-form>
    </el-card>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'

const form = reactive({
  ip: '',
  cidr: 24
})

const result = reactive({
  valid: false,
  networkAddress: '',
  broadcastAddress: '',
  firstUsableIp: '',
  lastUsableIp: '',
  totalHosts: '',
  subnetMask: '',
  error: ''
})

// 将数字转换为IP地址字符串
const numToIP = (num) => {
  const arr = []
  for (let i = 3; i >= 0; i--) {
    arr.push((num >> (i * 8)) & 255)
  }
  return arr.join('.')
}

// 将IP地址字符串转换为数字
const ipToNum = (ip) => {
  return ip.split('.').reduce((num, oct) => (num << 8) + parseInt(oct), 0) >>> 0
}

// 获取CIDR对应的子网掩码
const getCidrMask = (cidr) => {
  const mask = (0xffffffff << (32 - cidr)) >>> 0
  return numToIP(mask)
}

// 验证IP地址格式
const isValidIP = (ip) => {
  const parts = ip.split('.')
  if (parts.length !== 4) return false
  return parts.every(part => {
    const num = parseInt(part)
    return num >= 0 && num <= 255 && part === num.toString()
  })
}

// 计算子网信息
const calculate = () => {
  if (!form.ip) {
    result.valid = false
    result.error = '请输入IP地址'
    return
  }

  if (!isValidIP(form.ip)) {
    result.valid = false
    result.error = 'IP地址格式不正确'
    return
  }

  const ipNum = ipToNum(form.ip)
  const mask = (0xffffffff << (32 - form.cidr)) >>> 0
  const network = ipNum & mask
  const broadcast = network | (~mask >>> 0)
  
  result.valid = true
  result.networkAddress = numToIP(network)
  result.broadcastAddress = numToIP(broadcast)
  result.firstUsableIp = form.cidr === 31 || form.cidr === 32 
    ? result.networkAddress 
    : numToIP(network + 1)
  result.lastUsableIp = form.cidr === 31 || form.cidr === 32
    ? result.broadcastAddress
    : numToIP(broadcast - 1)
  result.totalHosts = form.cidr === 32 
    ? 1 
    : form.cidr === 31 
      ? 2 
      : Math.pow(2, 32 - form.cidr) - 2
  result.subnetMask = getCidrMask(form.cidr)
}
</script>

<style scoped>
.subnet-calculator {
  max-width: 800px;
  margin: 0 auto;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.result {
  margin-top: 20px;
}

h3 {
  margin: 0;
}
</style> 